/*
 *  Copyright 2019-2020 Zheng Jie
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *  http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */
package me.zhengjie.modules.mnt.rest

import cn.hutool.core.io.FileUtil
import cn.hutool.db.PageResult
import io.swagger.v3.oas.annotations.media.Schema
import jakarta.servlet.http.HttpServletRequest
import jakarta.servlet.http.HttpServletResponse
import me.zhengjie.common.exception.BadRequestException
import me.zhengjie.logging.annotation.Log
import me.zhengjie.modules.mnt.domain.Database
import me.zhengjie.modules.mnt.service.DatabaseService
import me.zhengjie.modules.mnt.service.dto.DatabaseDto
import me.zhengjie.modules.mnt.service.dto.DatabaseQueryCriteria
import me.zhengjie.modules.mnt.util.SqlUtils
import org.springframework.data.domain.Pageable
import org.springframework.http.HttpStatus
import org.springframework.http.ResponseEntity
import org.springframework.security.access.prepost.PreAuthorize
import org.springframework.validation.annotation.Validated
import org.springframework.web.bind.annotation.*
import org.springframework.web.multipart.MultipartFile
import java.io.File
import java.io.IOException

/**
 * @author zhanghouying
 * @date 2019-08-24
 */
@Schema(description = "运维：数据库管理")
@RestController
@RequestMapping("/api/database")
class DatabaseController {
    private val fileSavePath: String = FileUtil.getTmpDirPath() + "/"
    private val databaseService: DatabaseService? = null

    @Schema(description = "导出数据库数据")
    @GetMapping(value = ["/download"])
    @PreAuthorize("@el.check('database:list')")
    @Throws(
        IOException::class
    )
    fun exportDatabase(response: HttpServletResponse?, criteria: DatabaseQueryCriteria?) {
        databaseService!!.download(databaseService!!.queryAll(criteria), response)
    }

    @Schema(description =  "查询数据库")
    @GetMapping
    @PreAuthorize("@el.check('database:list')")
    fun queryDatabase(criteria: DatabaseQueryCriteria?, pageable: Pageable?): ResponseEntity<PageResult<DatabaseDto>> {
        return ResponseEntity<PageResult<DatabaseDto>>(databaseService!!.queryAll(criteria, pageable) as PageResult<DatabaseDto>, HttpStatus.OK)
    }

    @Log("新增数据库")
    @Schema(description =  "新增数据库")
    @PostMapping
    @PreAuthorize("@el.check('database:add')")
    fun createDatabase(@Validated @RequestBody resources: Database?): ResponseEntity<Any> {
        databaseService!!.create(resources!!)
        return ResponseEntity<Any>(HttpStatus.CREATED)
    }

    @Log("修改数据库")
    @Schema(description =  "修改数据库")
    @PutMapping
    @PreAuthorize("@el.check('database:edit')")
    fun updateDatabase(@Validated @RequestBody resources: Database?): ResponseEntity<Any> {
        databaseService!!.update(resources!!)
        return ResponseEntity<Any>(HttpStatus.NO_CONTENT)
    }

    @Log("删除数据库")
    @Schema(description =  "删除数据库")
    @DeleteMapping
    @PreAuthorize("@el.check('database:del')")
    fun deleteDatabase(@RequestBody ids: Set<String?>?): ResponseEntity<Any> {
        databaseService!!.delete(ids!!)
        return ResponseEntity<Any>(HttpStatus.OK)
    }

    @Log("测试数据库链接")
    @Schema(description = "测试数据库链接")
    @PostMapping("/testConnect")
    @PreAuthorize("@el.check('database:testConnect')")
    fun testConnect(@Validated @RequestBody resources: Database?): ResponseEntity<Any> {
        return ResponseEntity<Any>(databaseService!!.testConnection(resources!!), HttpStatus.CREATED)
    }

    @Log("执行SQL脚本")
    @Schema(description = "执行SQL脚本")
    @PostMapping(value = ["/upload"])
    @PreAuthorize("@el.check('database:add')")
    @Throws(
        Exception::class
    )
    fun uploadDatabase(@RequestBody file: MultipartFile, request: HttpServletRequest): ResponseEntity<Any> {
        val id: String = request.getParameter("id")
        val database: DatabaseDto = databaseService!!.findById(id)
        val fileName: String
        return if (database != null) {
            fileName = file.getOriginalFilename()!!
            val executeFile = File(fileSavePath + fileName)
            FileUtil.del(executeFile)
            file.transferTo(executeFile)
            val result = SqlUtils.executeFile(
                database.jdbcUrl!!,
                database.userName!!,
                database.pwd!!,
                executeFile
            )
            ResponseEntity<Any>(result, HttpStatus.OK)
        } else {
            throw BadRequestException("Database not exist")
        }
    }
}